Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(git): Add bcommits_range picker #2398

Merged
merged 12 commits into from
Jul 22, 2023

Conversation

aaronkollasch
Copy link
Contributor

@aaronkollasch aaronkollasch commented Feb 22, 2023

Description

fzf.vim has a feature where the :BCommits command shows only commits affecting the selected lines, if run from visual mode.

This functionality cannot be replicated in telescope with config options alone. Fzf.vim uses the arguments git log --no-patch -L start,end:file, which are not compatible with the filename that telescope appends to git_commands. (I tried some hacks like adding an argument to git_commands to make git ignore the filename argument, but they didn't work).

Type of change

This PR only affects bcommits behavior when run in visual mode, so I think it's a minor change but could be considered breaking.

This PR adds bcommits_range to show commits affecting a range of lines. bcommits_range can get the range of selected lines in visual mode, and supports an operator-pending mode to get lines from the next text object or motion. To support operators, this PR also adds a new telescope.operators module.

  • New feature (non-breaking change which adds functionality)
  • This change requires a documentation update

How Has This Been Tested?

  • Test A: Visually select lines of code, then activate the bcommits_range picker. Only commits affecting the selected lines should be shown. Check all previewer outputs to make sure they make sense.
  • Test B: Run test A from a subdirectory of the git directory. Behavior should be the same as before.
  • Test C: Run bcommits_range in normal mode, all commits for the file should be shown.
  • Test D: Run <cmd>Telescope git_bcommits_range first=1 last=10<CR> in normal mode. Commits affecting the first 10 lines should be shown.
  • Test E: Run <cmd>Telescope git_bcommits_range operator=true<CR> in normal mode followed by a motion or text object, e.g. ip for inner paragraph. All commits affecting the selected range should be shown.

Configuration:

  • Neovim version (nvim --version): v0.8.3
  • Operating system and version: macOS 13.2.1 Ventura

Notes

  • The line range in the file may not match the range used to filter commits, if there are uncommitted changes to the file (whether staged or not, it seems). This affects fzf.vim as well, and solving it could be tricky.
  • I've supported visual block mode by including a ^V in __git.lua, not sure if that's ok, or if there's a better way to detect visual mode.

Checklist:

  • My code follows the style guidelines of this project (stylua)
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (lua annotations)

@aaronkollasch aaronkollasch changed the base branch from dev to master February 22, 2023 08:56
@aaronkollasch aaronkollasch marked this pull request as ready for review February 27, 2023 19:48
@tjdevries
Copy link
Member

What do you think about just having a separate picker for this rather than overriding the original?

For example, we could have bcommits_range that accepts a start and end range, and we could generate those by default if it's in visual mode (but you could generate those other ways if you weren't in visual mode. For example, you could get the start and end range of a function with tree-sitter and then call this to get the commits over this function).

@aaronkollasch
Copy link
Contributor Author

A separate picker sounds good to me.

That would make it possible to define an operator-pending keymap for that picker. For example, I could type <bcommits_key>if or <bcommits_key>ip in normal mode to get the commits affecting a given function or paragraph. Perhaps this behavior could be enabled with an { operator = true } option? I don't know how to make operator keymaps yet, though.

Otherwise, bcommits_range with options { start = N, end = N } and auto-populating the range in visual mode makes sense to me.

@aaronkollasch
Copy link
Contributor Author

I pushed a commit with a separate bcommits_range picker. My one hesitation with this is the amount of repeated code/documentation, as any updates to bcommits would be expected to propagate to bcommits_range.

@aaronkollasch aaronkollasch force-pushed the visual-bcommit-filter branch 3 times, most recently from de717f6 to 6f8b9b2 Compare March 22, 2023 02:25
@aaronkollasch
Copy link
Contributor Author

I pushed a commit which adds operator mode as an option, and it works as expected. For example, <cmd>Telescope git_bcommits_range operator=true<CR> followed by if shows all commits affecting the function under the cursor.

@tjdevries
Copy link
Member

Love the operator pending stuff -- my only thought is that do you think it's possible to maybe move the operator pending logic outside of this function?

Perhaps we can make a new module telescope.operators. I think this idea is pretty cool and we may want to use the concept for some other pickers.

What are your thoughts on that?

@aaronkollasch aaronkollasch changed the title feat(git): Filter bcommits by selected range in visual mode feat(git): Add bcommits_range picker Mar 23, 2023
@aaronkollasch
Copy link
Contributor Author

That sounds good. I've updated the PR to move the operators functionality to telescope.operators.

@aaronkollasch aaronkollasch force-pushed the visual-bcommit-filter branch 3 times, most recently from 24be9dc to 77b4c4a Compare March 23, 2023 10:08
vim.o.operatorfunc = "v:lua.require'telescope.operators'.operator_callback"
-- feed g@ to enter operator-pending mode
-- 'i' required for which-key compatibility, etc.
vim.api.nvim_feedkeys("g@", "mi", false)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you think after running this line we should clear the operator? Or perhaps on line 7? This way we drop the reference to the picker and it can be garbage collected later, which seems like a good idea.

Maybe it should be:

operators.operator_callback = function()
  last_operator.callback(last_operator.opts)
  last_operator = { callback = function(_) end, opts = {} }
end

Copy link
Contributor Author

@aaronkollasch aaronkollasch Mar 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I tried something like that, but it breaks the key g@ to re-run the last operator. Not sure if that's a big deal or not as I don't use that keymap, but I didn't see a huge reason to break it.

How important is it to garbage collect the picker reference and opts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that makes sense.

It is kind of important, but it should be alright cause there is at most one outstanding, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, it's only a reference to the most recent picker/callback function used with operators.run_operator. At least for this picker it would just keep a reference to git.bcommits_range and its opts.

@aaronkollasch
Copy link
Contributor Author

aaronkollasch commented Apr 26, 2023

By the way, what do you think about the names of the arguments to specify the range? I'd originally used start and end but switched to first and last because the end keyword is a bit inconvenient in lua.
Would start and end make more sense?

edit: I will keep first and last due to the inconvenience of creating tables with an element named "end".

Default to a no-op callback
@aaronkollasch
Copy link
Contributor Author

I've rebased this PR on master to include the changes in #2597.

@jamestrew
Copy link
Contributor

Thanks for sticking with this^^
I'll try to review this in the coming days.

@jamestrew jamestrew self-assigned this Jul 19, 2023
@jamestrew
Copy link
Contributor

By the way, what do you think about the names of the arguments to specify the range? I'd originally used start and end but switched to first and last because the end keyword is a bit inconvenient in lua. Would start and end make more sense?

edit: I will keep first and last due to the inconvenience of creating tables with an element named "end".

Maybe from and to? Open to keeping first and last -- I think they work just as well

@aaronkollasch
Copy link
Contributor Author

By the way, what do you think about the names of the arguments to specify the range? I'd originally used start and end but switched to first and last because the end keyword is a bit inconvenient in lua. Would start and end make more sense?
edit: I will keep first and last due to the inconvenience of creating tables with an element named "end".

Maybe from and to? Open to keeping first and last -- I think they work just as well

from and to sound good, I think it's a bit more natural than first and last for specifying a range in a command.

@jamestrew
Copy link
Contributor

Beautiful. Thanks again 👍

@jamestrew jamestrew merged commit e7e6492 into nvim-telescope:master Jul 22, 2023
6 checks passed
@aaronkollasch
Copy link
Contributor Author

Thanks for reviewing!

@aaronkollasch aaronkollasch deleted the visual-bcommit-filter branch July 22, 2023 22:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants